package cn.zk.config;

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * MQ-死信队列
 */
@Configuration
public class DeathMessageConfig {
    // 死信交换机名称（就是普通交换机，叫法而已）
    public static final String EXCHANGE_DEATH = "exchange_death";
    // 死信队列名称 (就是普通队列，叫法而已)
    public static final String QUEUE_DEATH = "queue_death";
    // 死信队列 routingKey
    public static final String ROUTING_KEY_DEATH = "death.#";

    // 普通交换机名称
    public static final String EXCHANGE_TIME = "exchange_time";
    // 普通队列名称 (就是普通队列，叫法而已)
    public static final String QUEUE_TIME_10_SECOND = "queue_time_10_second";
    // 普通队列 routingKey
    public static final String ROUTING_KEY_TIME = "time.#";


    /**
     * 死信交换机配置
     *
     * ExchangeBuilder提供了fanout、direct、topic、header交换机类型的配置
     * @return the exchange
     */
    @Bean(EXCHANGE_DEATH)// 容器中的别名
    public Exchange exchangeDeath() {
        //durable(true)持久化，消息队列重启后交换机仍然存在
        return ExchangeBuilder.topicExchange(EXCHANGE_DEATH)// mq中交换机的别名
                .durable(true)
                .build();
    }

    //死信队列
    @Bean(QUEUE_DEATH)
    public Queue queueDeath() {
        Queue queue = new Queue(QUEUE_DEATH,true);
        return queue;
    }

    /**
     * 通配符：
     *      Routingkey 一般都是有一个或多个单词组成，多个单词之间以”.”分割
     *      #：匹配一个或多个词
     *      *：匹配不多不少恰好1个词
     * channel.queueBind(INFORM_QUEUE_SMS,"inform_exchange_topic","inform.#.sms.#");
     * 绑定队列到交换机 .
     *
     * @param queue    the queue
     * @param exchange the exchange
     * @return the binding
     */
    // 死信队列绑定死信交换机
    @Bean
    public Binding bindingQueueDeath(@Qualifier(QUEUE_DEATH) Queue queue,
                                            @Qualifier(EXCHANGE_DEATH) Exchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with(ROUTING_KEY_DEATH).noargs();
    }


    /**
     * 普通队列 （该队列不使用消费者消费，在这个队列中的消息会有过期特性，
     *          到期后就成为死信，根据配置发到死信交换机）
     *   队列的参数
     *   map.put("x-dead-letter-exchange", EXCHANGE_TOPICS);  //过期的消息给哪个交换机的名字
     *   map.put("x-dead-letter-routing-key", "death.#");   //死信交换机把消息个哪个个routingkey
     *   map.put("x-message-ttl", 10*1000);    //队列过期时间10s
     * @return
     */
    @Bean(QUEUE_TIME_10_SECOND)
    public Queue queueTime() {
        Map<String,Object> map = new HashMap<>();
        map.put("x-dead-letter-exchange", EXCHANGE_DEATH);  //过期的消息给哪个交换机的名字
        map.put("x-dead-letter-routing-key", "death.time");   //死信交换机把消息个哪个个routingkey
        map.put("x-message-ttl", 10*1000);    //队列过期时间10s
        return new Queue(QUEUE_TIME_10_SECOND,
                true,
                false,
                false,
                map);
    }


    // 普通交换机
    @Bean(EXCHANGE_TIME)// 容器中的别名
    public Exchange exchangeTime() {
        return ExchangeBuilder.topicExchange(EXCHANGE_TIME)// mq中交换机的别名
                .durable(true)
                .build();
    }

    // 普通队列绑定交换机
    @Bean
    public Binding bindingQueueTime(@Qualifier(QUEUE_TIME_10_SECOND) Queue queue,
                                    @Qualifier(EXCHANGE_TIME) Exchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with(ROUTING_KEY_TIME).noargs();
    }

}
